
package com.joysuch.wwyt.monitoringcenter.controller;

import cn.zlg.common.springmvc.validate.constraints.NotNull;
import com.joysuch.wwyt.bp.entity.AlarmMessage;
import com.joysuch.wwyt.bp.entity.InspectExceptionAlarmMesage;
import com.joysuch.wwyt.bp.service.AlarmMessageService;
import com.joysuch.wwyt.bp.service.BpWorkSafetyCertService;
import com.joysuch.wwyt.bp.service.InspectExceptionAlarmMesageService;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.bean.SimpleSelectListBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.enums.RiskLevels;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.mh.entity.MhAlarmMessage;
import com.joysuch.wwyt.mh.repository.MhAlarmMessageDao;
import com.joysuch.wwyt.mh.repository.MhMajorHazardDao;
import com.joysuch.wwyt.monitoringcenter.bean.*;
import com.joysuch.wwyt.monitoringcenter.service.LocateServerService;
import com.joysuch.wwyt.monitoringcenter.service.MonitoringCenterService;
import com.joysuch.wwyt.repeatsubmit.NoRepeatSubmit;
import com.joysuch.wwyt.risk.entity.RiskEvaluationControl;
import com.joysuch.wwyt.risk.repository.RiskDistrictDao;
import com.joysuch.wwyt.risk.repository.RiskEvaluationControlDao;
import com.joysuch.wwyt.risk.service.RiskEvaluationBusinessService;
import com.joysuch.wwyt.workflow.bean.ScreenColumnConfigBean;
import com.joysuch.wwyt.workflow.bean.ScreenConfigListBean;
import com.joysuch.wwyt.workflow.bean.ScreenConfigListReturnBean;
import com.joysuch.wwyt.workflow.bean.WorkFlowSearchBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.batik.transcoder.keys.StringKey;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.redisson.api.RList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.persistence.Tuple;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@RestController
@RequestMapping("/monitoring-center")
@Api(tags = "/monitoring-center 监测中心")
public class MonitoringCenterController {

    @Autowired
    private MhMajorHazardDao mhMajorHazardDao;
    @Autowired
    private MhAlarmMessageDao messageDao;

    @Autowired
    private RiskDistrictDao riskDistrictDao;
    @Autowired
    private MonitoringCenterService monitoringCenterService;

    @Autowired
    private BpWorkSafetyCertService bpWorkSafetyCertService;

    @Autowired
    private LocateServerService locateServerService;

    @Autowired
    private AlarmMessageService alarmMessageService;

    @Autowired
    private RiskEvaluationBusinessService riskEvaluationBusinessService;

    @Autowired
    private InspectExceptionAlarmMesageService inspectAlarmMesageService;

    @Autowired
    private RiskEvaluationControlDao controlDao;

    @Autowired
    private RedisClient redisClient;

    @RequestMapping("/mh-realtime")
    @ApiOperation("大屏-重大危险源监测数据")
    public Object majorHazardRealtimeData(Integer pageNumber, Integer pageSize) {
        MajarHazardRealtimeDataMonitoringBean result = monitoringCenterService.majorHazardRealtimeData(pageNumber, pageSize);
        return ResultBean.success(result);
    }

    /**
     * 1. 风险区域 - 重大危险源 ，统计每个风险区域内的重大危险源数量
     * 2. 是全部监测点产生的报警数量，以时间为单位，返回1周的数据
     * 3. 现在加上AI报警和巡检排查报警
     *
     * @return
     */
    @RequestMapping("/mh-stat")
    public Object majorHazardStat() {
        MajarHazardStatBean bean = new MajarHazardStatBean();
        List dangerCounts = mhMajorHazardDao.statDangerCount();
        List<MajarHazardDangerCountBean> lists = convertToLists(dangerCounts);
        bean.setDangerCount(lists);
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = now.minusDays(6);
        startTime = startTime.minusHours(startTime.getHour());
        startTime = startTime.minusMinutes(startTime.getMinute());
        startTime = startTime.minusSeconds(startTime.getSecond());
        startTime = startTime.minusNanos(startTime.getNano());

        // System.out.println(startTime);
        //时间内的重大危险源报警
        List<MhAlarmMessage> messages = messageDao.statsForCountInDay(startTime);
        //时间内的AI报警
        List<AlarmMessage> aiMessageList = alarmMessageService.statsForCountInDay(startTime, Context.getCurrentTenantId(), Context.getCurrentOrgCode());
        //时间内的巡检排查报警
        List<InspectExceptionAlarmMesage> inspectMessageList = inspectAlarmMesageService.statsForCountInDay(startTime, Context.getCurrentTenantId(), Context.getCurrentOrgCode());

        List<MajarHazardWarnCountBean> warnCount = statsWarnCounts(messages, aiMessageList, inspectMessageList, startTime, 7);
        bean.setDangerCount(lists);
        bean.setWarnCount(warnCount);
        return ResultBean.success(bean);
    }

    private List<MajarHazardDangerCountBean> convertToLists(List dangerCounts) {
        List<MajarHazardDangerCountBean> re = new ArrayList<>();
        for (Object o : dangerCounts) {
            Tuple t = (Tuple) o;
            MajarHazardDangerCountBean b = new MajarHazardDangerCountBean();
            b.setName((String) t.get("name"));
//            b.setValue(((Long) t.get("value")).intValue());
            b.setValue(Integer.valueOf(t.get("value").toString()));
            re.add(b);
        }
        return re;
    }

    private List<MajarHazardWarnCountBean> statsWarnCounts(List<MhAlarmMessage> messages, List<AlarmMessage> aiMessageList,
                                                           List<InspectExceptionAlarmMesage> inspectMessageList, LocalDateTime startTime,
                                                           int days) {
        TreeMap map = new TreeMap<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");
        for (int i = 0; i < days; i++) {
            String tag = formatter.format(startTime.plusDays(i));
            MajarHazardWarnCountBean object = new MajarHazardWarnCountBean();
            object.setTime(tag);
            object.setValue(0);
            map.put(tag, object);
        }
        for (MhAlarmMessage m : messages) {
            String tag = formatter.format(m.getAlarmTime());
            MajarHazardWarnCountBean object = (MajarHazardWarnCountBean) map.get(tag);
            if (object != null) {
                object.setValue(object.getValue() + 1);
            }
        }
        for (AlarmMessage alarmMessage : aiMessageList) {
            String tag = new SimpleDateFormat("MM/dd").format(alarmMessage.getAlarmTime());
            MajarHazardWarnCountBean object = (MajarHazardWarnCountBean) map.get(tag);
            if (object != null) {
                object.setValue(object.getValue() + 1);
            }
        }
        for (InspectExceptionAlarmMesage message : inspectMessageList) {
            String tag = new SimpleDateFormat("MM/dd").format(message.getAlarmTime());
            MajarHazardWarnCountBean object = (MajarHazardWarnCountBean) map.get(tag);
            if (object != null) {
                object.setValue(object.getValue() + 1);
            }
        }
        return new ArrayList<>(map.values());
    }

    // 设备设施详情
    @RequestMapping("/get-facility-detail")
    @ApiOperation("大屏-设备设施详情")
    public Object getFacilityDetail(Long id) {
        DeviceFacilityStatusBean re = monitoringCenterService.getDeviceFacilityStatusBean(id);
        return ResultBean.success(re);
    }


    /**
     * 区域风险程度统计
     *
     * @return
     */
    @RequestMapping("/risk-level-statistics")
    public Object riskLevelStatistics() {

        RiskEvaluationControl control = controlDao.findByName("动态安全风险评估");
        // 填写风险管控信息
        List<Tuple> counts = null;
        if (control != null && control.getSwitchState() == 0) {
            //计算实时等级
            counts = riskDistrictDao.groupDistrictLevelCount();
        } else {
            //计算动态值
            counts = riskDistrictDao.groupDistrictDynamicLevelCount();
        }

        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>(4);
        for (RiskLevels r : RiskLevels.values()) {
            Map<String, Object> m = new HashMap<>();
            m.put("name", r.getName());
            m.put("value", 0);
            list.add(m);
        }
        for (Tuple t : counts) {
            String name = RiskLevels.findRiskLevelName((Integer) t.get(1));
            Map<String, Object> m = findLevel(list, name);
            m.put("value", t.get(0));
        }
        map.put("areaDangerCount", list);
        map.put("specialWorkCount", bpWorkSafetyCertService.specialWorkCount());
        return ResultBean.success(map);
    }

    private Map<String, Object> findLevel(List<Map<String, Object>> list, String name) {
        for (Map<String, Object> m : list) {
            if (m.get("name").equals(name)) {
                return m;
            }
        }
        return null;
    }

    // 区域风险详情
    @GetMapping("/district-risk-detail")
    @ApiOperation("大屏-区域详情")
    public Object findDistrictRiskDetail(Pageable pageable, Long id, String version) {
        DistrictRiskDetailBean bean = monitoringCenterService.queryDistrictRiskDetail(pageable, id, version);
        return ResultBean.success(bean);
    }

    // 重大危险源监测详情
    @RequestMapping("/mh-detail")
    @ApiOperation("大屏-重大危险源监测详情")
    public Object getMhDetail(Long id) {
        return ResultBean.success(monitoringCenterService.queryMajorHazardDetail(id));
    }

    // 风险分区列表
    @RequestMapping("/risk-district-list")
    public Object getRiskDistrictList() {
        return ResultBean.success(monitoringCenterService.queryRiskDistrictList());
    }

    // 风险分区列表
    @RequestMapping("/monitoring-point-detail")
    public Object getMonitoringPointDetail(@Valid @NotNull(field = "监测点ID") Long id) {
        try {
            return ResultBean.success(monitoringCenterService.queryMonitoringPointDetail(id));
        } catch (ApiBusinessException e) {
            return ResultBean.fail(Status.MONITOR_POINT_NOT_FIND_ERROR);
        }
    }

    //根据监测点id以及时间范围查询范围内的报警信息
    @GetMapping("/getAlarmByPoint")
    @ApiOperation(value = "根据监测点id以及时间段查询范围内的报警")
    public ResultBean getAlarmByPoint(Long id, Date startTime, Date endTime) {
        return ResultBean.success(monitoringCenterService.getAlarmByPoint(id, startTime, endTime));

    }

    // 查询执行中的作业证列表
    @RequestMapping("/work-safety-cert-in-progressing")
    public Object getWorkSafetyCertsInProgressing() {
        return ResultBean.success(monitoringCenterService.queryAllInProgressingWorkSafetyCerts());
    }

    // 报警信息列表
    @RequestMapping("/alarm-message-queue")
    public Object getAlarmMessageQueue(String type, Long riskDistrictId, Integer state, Integer offset, Integer count) {
        if (offset == null || offset < 0) {
            offset = 0;
        }
        if (count == null || count < 0 || count > 1000) {
            count = 100;
        }
        List<McAlarmMessageBean> mcAlarmMessageBeans = monitoringCenterService.queryAlarmMessages(type, riskDistrictId,
                state, offset, count);
        // mcAlarmMessageBeans.addAll(locateServerService.alarmMessages());
        return ResultBean.success(mcAlarmMessageBeans);
    }

    //报警数量
    @RequestMapping("alarm-message-count")
    @ApiOperation("报警数量查询")
    public ResultBean alarmMessageCount(String buildId) {
        return monitoringCenterService.alarmMessageCount(buildId);
    }

    /**
     * 处理消息统一入口
     *
     * @param bean
     * @return 处理状态
     */
    @RequiresPermissions("monitoring-center:process-alarm")
    @RequestMapping("/process-alarm-message")
    @NoRepeatSubmit(paramNames = "id")
    public Object processAlarmMessage(@RequestBody MonitoringCenterInBean bean) {
        String type = bean.getType();
        Long id = bean.getId();
        String module = bean.getModule();
        String msg = bean.getMsg();
        String alarmReason = bean.getAlarmReason();
        Long handleBy = bean.getHandleBy();
        Integer handleFlag = bean.getHandleFlag();
        Assert.notNull(type, "type不能为空");
        Assert.notNull(id, "id不能为空");
        if ("重大危险源".equals(module) || "风险分区".equals(module) || "人员在岗在位".equals(module) || "巡检排查".equals(module) || "AI报警".equals(module)
                || "人员在岗在位报警".equals(module) || "作业票报警".equals(module) || "车辆报警".equals(module)) {
            // 为了兼容前端写的恶心代码，将消息原样传了回来
            type = module;
        }
        monitoringCenterService.processAlarmMessage(type, id, msg, alarmReason, handleBy, handleFlag);
        return ResultBean.success("");
    }

    /**
     * 批量处理报警消息
     *
     * @param
     * @return
     */

    @RequiresPermissions("monitoring-center:process-alarm")
    @PostMapping("/process-alarm-batch")
    public Object processAlarmBatch(@RequestBody List<AlarmProcessBean> list) {
        monitoringCenterService.processAlarmMessageBatch(list);
        return ResultBean.success("");
    }

    /**
     * test
     *
     * @param
     * @return
     */

    @GetMapping("/sync-test")
    public Object syncTest(String key) {
        List<InspectExceptionAlarmMesage> inspectList = new ArrayList<>();
        InspectExceptionAlarmMesage mesage = new InspectExceptionAlarmMesage();
        mesage.setTenentId(1L);
        mesage.setOrgCode("001-001");
        mesage.setProcInstId(key);
        inspectList.add(mesage);
        boolean flag = monitoringCenterService.syncWorkFlow(inspectList);
        return ResultBean.success("");
    }


    /**
     * 批量处理所有报警消息
     *
     * @param
     * @return
     */

    @RequiresPermissions("monitoring-center:process-alarm")
    @PostMapping("/process-alarm-batch-all")
    @ApiOperation("一键报警处理")
    public ResultBean processAlarmBatchAll(@RequestBody @Valid CenterAlarmMessageHandlerBean bean) {
        monitoringCenterService.processAlarmBatchAll(bean);
        return ResultBean.success("");
    }

    /**
     * 查询新生成的消息列表，用于生成消息提示音
     *
     * @return
     */
    @RequestMapping("/new-alarm-message")
    public Object getNewAlarmMessage() {
        List<NewAlarmMessage> list = monitoringCenterService.findNewAlarmMessage();
        return ResultBean.success(list);
    }

    /**
     * 流程引擎-大屏
     * searchMap:  key 专栏名称; value 搜索条件
     */
    @PostMapping("workFlow-screen")
    @ApiOperation("监控大屏-获取需要显示的流程引擎业务数据")
    public ResultBean workFlowScreen(@RequestBody WorkFlowSearchBean searchMap) {
        return monitoringCenterService.workFlowScreen(searchMap);
    }


    @GetMapping("/getCenterMajorHazardTypeList")
    @ApiOperation("大屏-重大危险源监测预警类型列表")
    public ResultBean getCenterMajorHazardTypeList() {
        List<SimpleSelectListBean> list = monitoringCenterService.getCenterMajorHazardTypeList();
        return ResultBean.success(list);
    }


    @GetMapping("/getRiskDistrictLevelList")
    @ApiOperation("大屏-风险四色图风险等级列表")
    public ResultBean getRiskDistrictLevelList() {
        List<SimpleSelectListBean> list = monitoringCenterService.getRiskDistrictLevelList();
        return ResultBean.success(list);
    }

    @GetMapping("/centerRiskDistrictPage")
    @ApiOperation("大屏-风险四色图列表")
    public ResultBean centerRiskDistrictPage(Pageable page, CenterRiskDistrictSearchBean condition) {
        return monitoringCenterService.centerRiskDistrictPage(page, condition);
    }

    @GetMapping("/centerMajorHazardPage")
    @ApiOperation("大屏-重大危险源监测预警列表")
    public ResultBean centerMajorHazardPage(Pageable page, CenterMajorHazardSearchBean condition) {
        return monitoringCenterService.centerMajorHazardPage(page, condition);
    }

    @GetMapping("/centerManuFacturingTechPage")
    @ApiOperation("大屏-工艺流程列表")
    public ResultBean centerManuFacturingTechPage(Pageable page, String name) {
        return monitoringCenterService.centerManuFacturingTechPage(page, name);
    }

    @GetMapping("/getManuFacturingTechById")
    @ApiOperation("大屏-工艺流程详情")
    public ResultBean centerManuFacturingTechPage(Long id) {
        CenterManuFacturingTechBean bean = monitoringCenterService.getManuFacturingTechById(id);
        return ResultBean.success(bean);
    }

    @GetMapping("/locate-login-token")
    @ApiOperation("人员在岗在位获取登录token")
    public ResultBean locateLoginToken() {
        return ResultBean.success(locateServerService.getLoginToken());
    }

    @GetMapping("/all-column")
    @ApiOperation(value = "获取所有专栏", response = ScreenColumnBean.class)
    public ResultBean allColumn() {
        return monitoringCenterService.allColumn();
    }

    @GetMapping("/getAllColumn")
    @ApiOperation(value = "获取所有专栏", response = ScreenColumnBean.class)
    public ResultBean getAllColumn() {
        return monitoringCenterService.getAllColumn();
    }

    @GetMapping("/getScreenTypeList")
    @ApiOperation("大屏-专栏")
    public ResultBean getScreenTypeList() {
        ScreenTypeAndConfigBean bean = monitoringCenterService.getScreenTypeList();
        return ResultBean.success(bean);
    }

    @GetMapping("/getScreenAllConfigList")
    @ApiOperation("大屏-勾选专栏配置")
    public ResultBean getScreenAllConfigList(Long typeId) {
        List<ScreenConfigListBean> list = monitoringCenterService.getScreenAllConfigList(typeId);
        return ResultBean.success(list);
    }

    //todo 待删除
    @GetMapping("/column-list")
    @ApiOperation(value = "根据专栏id/名称查询相关配置", response = ScreenColumnConfigBean.class)
    public ResultBean columnList(ScreenColumnBean screenColumnBean) {
        return monitoringCenterService.columnList(screenColumnBean);
    }

    //todo 待删除
    @PostMapping("/column-save")
    @ApiOperation("专栏配置保存")
    public ResultBean columnSave(@RequestBody ScreenColumnConfigBean bean) {
        return monitoringCenterService.columnSave(bean);
    }

    @PostMapping("/screenColumnSave")
    @ApiOperation("专栏配置保存")
    public ResultBean screenColumnSave(@RequestBody ScreenConfigListReturnBean bean) {
        return monitoringCenterService.screenColumnSave(bean);
    }


    @GetMapping("/getPlanListByHazardId")
    @ApiOperation(value = "获取危险源关联的预案列表")
    public ResultBean getPlanListByHazardId(Long hazardId) {
        List<CenterEmergencyPlanBean> list = monitoringCenterService.getPlanListByHazardId(hazardId);
        return ResultBean.success(list);
    }

    @GetMapping("/getScreenPeopleCaps")
    @ApiOperation(value = "大屏人员/承包商人员 帽子信息")
    public ResultBean getScreenPeopleCaps() {
        List<ScreenPeopleCapBean> list = monitoringCenterService.getScreenPeopleCaps();
        return ResultBean.success(list);
    }

    @GetMapping("/getAllfacility")
    @ApiOperation("大屏-设备")
    public ResultBean getAllfacility() {
        return monitoringCenterService.getAllfacility();
    }
}
